package cn.youqu.happy.module.youqu.service.userTell;

import cn.youqu.happy.framework.common.pojo.PageResult;
import cn.youqu.happy.module.member.dal.dataobject.user.MemberUserDO;
import cn.youqu.happy.module.member.service.user.MemberUserService;
import cn.youqu.happy.module.youqu.controller.admin.userTell.vo.UserTellCreateReqVO;
import cn.youqu.happy.module.youqu.controller.admin.userTell.vo.UserTellExportReqVO;
import cn.youqu.happy.module.youqu.controller.admin.userTell.vo.UserTellPageReqVO;
import cn.youqu.happy.module.youqu.controller.admin.userTell.vo.UserTellUpdateReqVO;
import cn.youqu.happy.module.youqu.controller.app.userTell.vo.AppUserTellPublishReqVO;
import cn.youqu.happy.module.youqu.controller.app.userTell.vo.AppUserTellUpdateReqVO;
import cn.youqu.happy.module.youqu.convert.userTell.UserTellConvert;
import cn.youqu.happy.module.youqu.dal.dataobject.userActivity.UserActivityDO;
import cn.youqu.happy.module.youqu.dal.dataobject.userArrange.UserArrangeDO;
import cn.youqu.happy.module.youqu.dal.dataobject.userBlack.UserBlackDO;
import cn.youqu.happy.module.youqu.dal.dataobject.userTell.UserTellDO;
import cn.youqu.happy.module.youqu.dal.mysql.userTell.UserTellMapper;
import cn.youqu.happy.module.youqu.enums.userArrange.UserArrangeStatusEnum;
import cn.youqu.happy.module.youqu.enums.userBalck.UserBlackTypeEnum;
import cn.youqu.happy.module.youqu.enums.userTell.UserTellStatusEnum;
import cn.youqu.happy.module.youqu.enums.userTell.UserTellTimeTypeEnum;
import cn.youqu.happy.module.youqu.service.userActivity.UserActivityService;
import cn.youqu.happy.module.youqu.service.userArrange.UserArrangeService;
import cn.youqu.happy.module.youqu.service.userBlack.UserBlackService;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static cn.youqu.happy.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.youqu.happy.framework.common.util.string.StrUtils.stringConvertToList;
import static cn.youqu.happy.module.youqu.enums.ErrorCodeConstants.*;

/**
 * 用户说说 Service 实现类
 *
 * @author 王其岩 20112001045
 */
@Service
@Validated
public class UserTellServiceImpl implements UserTellService {

    @Resource
    private UserTellMapper userTellMapper;

    @Resource
    @Lazy
    private UserArrangeService userArrangeService;

    @Resource
    @Lazy
    private UserActivityService userActivityService;

    @Resource
    @Lazy
    private MemberUserService memberUserService;
    @Resource
    @Lazy
    private UserBlackService userBlackService;

    @Override
    public Integer createUserTell(UserTellCreateReqVO createReqVO) {
        // 插入
        UserTellDO userTell = UserTellConvert.INSTANCE.convert(createReqVO);
        userTellMapper.insert(userTell);
        // 返回
        return userTell.getId();
    }

    @Override
    public Integer publishUserTell(AppUserTellPublishReqVO publishReqVO, Long loginUserId) {
        // 校验活动id是否存在
        UserActivityDO userActivity = userActivityService.getUserActivity(publishReqVO.getActivityId());
        if (userActivity == null) {
            throw exception(USER_ACTIVITY_NOT_EXISTS);
        }
        //校验是否生成计划
        UserArrangeDO userArrange0 = userArrangeService.getUserArrange0(publishReqVO.getActivityId());
        if (userArrange0 == null) {
            throw exception(USER_ARRANGE_NOT_EXISTS);
        }


        UserTellDO userTell = UserTellConvert.INSTANCE.convert(publishReqVO);

        //设置时间类型
        if (Objects.equals(userArrange0.getArrangeStatus(), UserArrangeStatusEnum.ARRANGE_WAITING.getStatus())) {
            userTell.setTimeType(UserTellTimeTypeEnum.BEFORE.getType());
        } else if (Objects.equals(userArrange0.getArrangeStatus(), UserArrangeStatusEnum.ARRANGE_ING.getStatus())) {
            userTell.setTimeType(UserTellTimeTypeEnum.ING.getType());
        } else if (Objects.equals(userArrange0.getArrangeStatus(), UserArrangeStatusEnum.ARRANGE_END.getStatus())) {
            userTell.setTimeType(UserTellTimeTypeEnum.END.getType());
        }
        //设置默认值  已在convent 中实现
//        userTell.setImg(ListConvertToString(publishReqVO.getImgList()));
        //设置 发表人
        userTell.setUid(loginUserId);
        MemberUserDO user = memberUserService.getUser(loginUserId);
        //设置用户头像 冗余字段
        userTell.setAvatar(user.getAvatar());
        //设置用户昵称 冗余字段
        userTell.setNickName(user.getNickname());
        //设置活动名名 冗余字段
        userTell.setActivityName(userActivity.getActivityName());
        //设置系统活动id 用于推荐友说
        userTell.setSysActivityId(userActivity.getActivityId());
        //设置队友 冗余字段
        userTell.setPartners(userActivity.getPartners());
        userTellMapper.insert(userTell);
        return userTell.getId();
    }


    @Override
    public void updateUserTell(UserTellUpdateReqVO updateReqVO) {
        // 校验存在
        this.validateUserTellExists(updateReqVO.getId());
        // 更新
        UserTellDO updateObj = UserTellConvert.INSTANCE.convert(updateReqVO);
        userTellMapper.updateById(updateObj);
    }

    @Override
    public void deleteUserTell(Integer id) {
        // 校验存在
        this.validateUserTellExists(id);
        // 删除
        userTellMapper.deleteById(id);
    }

    @Override
    public void deleteUserTell(Integer id, Long loginUserId) {
        this.validateUserOwnUserTell(id, loginUserId);
        userTellMapper.deleteById(id);
    }

    private void validateUserTellExists(Integer id) {
        if (userTellMapper.selectById(id) == null) {
            throw exception(USER_TELL_NOT_EXISTS);
        }
    }

    @Override
    public UserTellDO getUserTell(Integer id) {
        return userTellMapper.selectById(id);
    }

    @Override
    public UserTellDO getUserTell(Integer id, Long uid) {
        return userTellMapper.findOneByIdAndUid(id, uid);
    }

    @Override
    public List<UserTellDO> getUserTellList(Collection<Integer> ids) {
        return userTellMapper.selectBatchIds(ids);
    }

    @Override
    public List<UserTellDO> getUserTellList(Collection<Integer> ids, Long uid) {
        List<UserTellDO> userTellDOS = userTellMapper.selectBatchIds(ids);
        return filterOwnUserTell(userTellDOS, uid);
    }

    @Override
    public PageResult<UserTellDO> getUserTellPage(UserTellPageReqVO pageReqVO) {
        return userTellMapper.selectPage(pageReqVO);
    }

    @Override
    public PageResult<UserTellDO> getUserTellPage(UserTellPageReqVO pageReqVO, Long uid) {
        PageResult<UserTellDO> userTellDOPageResult = userTellMapper.selectPage(pageReqVO);
        List<UserTellDO> list = userTellDOPageResult.getList();
        List<UserTellDO> userTellDOS = filterOwnUserTell(list, uid);
        userTellDOPageResult.setList(userTellDOS);
        userTellDOPageResult.setTotal((long) userTellDOS.size());
        return userTellDOPageResult;
    }

    @Override
    public PageResult<UserTellDO> getUserTellSquarePage(UserTellPageReqVO pageReqVO, Long uid) {
        PageResult<UserTellDO> userTellDOPageResult = userTellMapper.selectPage(pageReqVO);
        List<UserTellDO> list = userTellDOPageResult.getList();
        List<UserTellDO> userTellDOS = filterCanSeeUserTell(list, uid);
        userTellDOPageResult.setList(userTellDOS);
        userTellDOPageResult.setTotal((long) userTellDOS.size());
        return userTellDOPageResult;
    }

    @Override
    public PageResult<UserTellDO> getUserTellPartnerPage(UserTellPageReqVO pageReqVO, Long uid) {
        Integer startIndex = (pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize();
        PageResult<UserTellDO> userTellDOPageResult = new PageResult<>();
        List<UserTellDO> list = userTellMapper.selectPartnerPage(pageReqVO, uid, startIndex, pageReqVO.getPageSize());
        //筛选用户可见的
        List<UserTellDO> userTellDOS = filterCanSeeUserTell(list, uid);
        userTellDOPageResult.setList(userTellDOS);
        userTellDOPageResult.setTotal((long) list.size());
        return userTellDOPageResult;
    }

    private List<UserTellDO> filterOwnUserTell(List<UserTellDO> userTellDOs, Long uid) {
        return userTellDOs.stream().filter(item -> uid.equals(item.getUid())).collect(Collectors.toList());

    }

    private List<UserTellDO> filterCanSeeUserTell(List<UserTellDO> userTellDOs, Long uid) {
        //避免重复查询
        return userTellDOs.stream().filter(item -> validateUserCanSeeUserTell(item, uid)).collect(Collectors.toList());
    }


    @Override
    public List<UserTellDO> getUserTellList(UserTellExportReqVO exportReqVO) {
        return userTellMapper.selectList(exportReqVO);
    }

    @Override
    public boolean validateUserOwnUserTell(Integer id, Long uid) {
        UserTellDO userTellDO = userTellMapper.selectById(id);
        if (userTellDO == null) {
            throw exception(USER_TELL_NOT_EXISTS);
        } else if (uid.equals(userTellDO.getUid())) {
            return true;
        } else {
            throw exception(USER_TELL_NOT_EXISTS);
        }
    }

    @Override
    public void updateUserTell(AppUserTellUpdateReqVO updateReqVO, Long loginUserId) {
        this.validateUserOwnUserTell(updateReqVO.getId(), loginUserId);
        UserTellDO convert = UserTellConvert.INSTANCE.convert(updateReqVO);
        //已在convent 中实现
        //convert.setImg(ListConvertToString(updateReqVO.getImgList()));
        userTellMapper.updateById(convert);
    }

    @Override
    public boolean validateUserCanSeeUserTell(Integer id, Long uid) {
        UserTellDO userTellDO = userTellMapper.selectById(id);
        if (userTellDO == null) {
            return false;
        } else if (uid.equals(userTellDO.getUid())) {
            return true;
        } else {
            // 判断是否在黑名单内
            UserBlackDO userBlack = userBlackService.getUserBlack(uid, userTellDO.getUid());
            if (userBlack != null) {
                //判断拉黑类型是否是说说
                if (userBlack.getBlackType().equals(UserBlackTypeEnum.ALL.getType()) ||
                        userBlack.getBlackType().equals(UserBlackTypeEnum.CAN_NOT_SEE_MY_TELL.getType())) {
                    return true;
                }
            }
            if (userTellDO.getTellStatus().equals(UserTellStatusEnum.PRIVATE_OWN.getStatus())) {
                return false;
            } else if (userTellDO.getTellStatus().equals(UserTellStatusEnum.PRIVATE_PARTNER.getStatus())) {
                String partners = userTellDO.getPartners();
                List<String> partnerArr = stringConvertToList(partners);
                return partnerArr.stream().anyMatch(item -> String.valueOf(uid).equals(item));
            }
        }
        return false;
    }

    public boolean validateUserCanSeeUserTell(UserTellDO userTellDO, Long uid) {
        //避免重复查询
        if (userTellDO == null) {
            return false;
        } else if (uid.equals(userTellDO.getUid())) {
            return true;
        } else {
            // 判断是否在黑名单内
            UserBlackDO userBlack = userBlackService.getUserBlack(uid, userTellDO.getUid());
            if (userBlack != null) {
                //判断拉黑类型是否是说说
                if (userBlack.getBlackType().equals(UserBlackTypeEnum.ALL.getType()) ||
                        userBlack.getBlackType().equals(UserBlackTypeEnum.CAN_NOT_SEE_MY_TELL.getType())) {
                    return true;
                }
            }
            if (userTellDO.getTellStatus().equals(UserTellStatusEnum.PRIVATE_OWN.getStatus())) {
                return false;
            } else if (userTellDO.getTellStatus().equals(UserTellStatusEnum.PRIVATE_PARTNER.getStatus())) {
                String partners = userTellDO.getPartners();
                List<String> partnerArr = stringConvertToList(partners);
                return partnerArr.stream().anyMatch(item -> String.valueOf(uid).equals(item));
            }
        }
        return false;
    }

    @Override
    public boolean validatePartnerUserTell(Integer id, Long uid) {
        //TODO
        return false;
    }

    @Override
    public void updateUserInfoToUserTell(String nickname, String avatar, Long uid) {
        if (nickname != null) {
            userTellMapper.updateNickNameByUid(nickname, uid);
        }
        if (avatar != null) {
            userTellMapper.updateAvatarByUid(avatar, uid);
        }
    }

}
